package com.changgou.seckill.task;

import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Set;

@Component
public class SeckillGoodsPushTask {

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    public static final String SECKILL_GOODS_KEY="seckill_goods_";

    public static final String SECKILL_GOODS_STOCK_COUNT_KEY="seckill_goods_stock_count_";

    /**
     * 定时任务：将符合条件的秒杀商品加载到Redis缓存中。
     * 该函数每30秒执行一次，查询符合条件的秒杀商品，并将其存入Redis缓存中。
     * 查询条件包括：
     * 1. 商品状态为审核通过（status=1）。
     * 2. 商品库存大于0。
     * 3. 秒杀商品的开始时间大于等于当前时间段。
     * 4. 秒杀商品的结束时间小于当前时间段加2小时。
     * 5. 排除已经加载到Redis缓存中的商品。
     * 查询结果将根据时间段分类，并存入Redis中，同时将商品的库存数量也存入Redis。
     */
    @Scheduled(cron = "0/30 * * * * ?")
    public void loadSecKillGoodsToRedis() {
        // 获取当前时间段的5个时间点
        List<Date> dateMenus = DateUtil.getDateMenus();

        // 遍历每个时间段，查询符合条件的秒杀商品
        for (Date dateMenu : dateMenus) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            // 将当前时间段转换为字符串，用于Redis中的key
            String redisExtName = DateUtil.date2Str(dateMenu);

            // 创建查询条件
            Example example = new Example(SeckillGoods.class);
            Example.Criteria criteria = example.createCriteria();

            // 设置查询条件：状态为审核通过、库存大于0、开始时间大于等于当前时间段、结束时间小于当前时间段加2小时
            criteria.andEqualTo("status", "1");
            criteria.andGreaterThan("stockCount", 0);
            criteria.andGreaterThanOrEqualTo("startTime", simpleDateFormat.format(dateMenu));
            criteria.andLessThan("endTime", simpleDateFormat.format(DateUtil.addDateHour(dateMenu, 2)));

            // 获取Redis中已经存在的商品ID，排除这些商品
            Set keys = redisTemplate.boundHashOps(SECKILL_GOODS_KEY + redisExtName).keys();
            if (keys != null && keys.size() > 0) {
                criteria.andNotIn("id", keys);
            }

            // 执行查询，获取符合条件的秒杀商品列表
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectByExample(example);

            // 将查询到的秒杀商品存入Redis缓存
            for (SeckillGoods seckillGoods : seckillGoodsList) {
                redisTemplate.opsForHash().put(SECKILL_GOODS_KEY + redisExtName, seckillGoods.getId(), seckillGoods);

                // 将秒杀商品的库存数量存入Redis
                redisTemplate.opsForValue().set(SECKILL_GOODS_STOCK_COUNT_KEY + seckillGoods.getId(), seckillGoods.getStockCount());
            }
        }
    }
}
